package com.shrct.businessprocess.product.impl;

import com.google.common.base.Objects;
import com.shrct.businessprocess.budget.RCBudget;
import com.shrct.businessprocess.product.RCActualServicePurchased;
import com.shrct.businessprocess.product.RCCompanyServiceEntry;
import com.shrct.businessprocess.product.RCFullServiceProductEntry;
import com.shrct.businessprocess.product.RCIdentifiablePhysicalProductEntry;
import com.shrct.businessprocess.product.RCProductServiceStatus;
import com.shrct.businessprocess.product.RCProductServiceTracer;
import com.shrct.businessprocess.product.impl.RCActualServicePurchasedImpl;
import com.shrct.businessprocess.product.impl.RCCompanyServiceEntryImpl;
import com.shrct.businessprocess.product.impl.RCIdentifiablePhysicalProductEntryImpl;
import com.shrct.businessprocess.product.proxy.RCProductServiceTracerProxy;
import com.shrct.businessprocess.purchase.RCBudgetContract;
import com.shrct.businessprocess.purchase.RCHasPurchaseBudget;
import com.shrct.businessprocess.purchase.impl.RCBudgetContractImpl;
import edu.fudan.mylang.pf.BaseModelObject;
import edu.fudan.mylang.pf.IObjectFactory;
import edu.fudan.mylang.utils.DateUtil;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.DiscriminatorColumn;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import org.eclipse.xtext.xbase.lib.Functions.Function1;
import org.eclipse.xtext.xbase.lib.IterableExtensions;
import org.eclipse.xtext.xbase.lib.ObjectExtensions;
import org.eclipse.xtext.xbase.lib.Procedures.Procedure1;
import org.hibernate.annotations.DiscriminatorOptions;

@Entity
@DiscriminatorValue("RCPRODUCTSERVICETRACER_TYPE")
@DiscriminatorOptions(force = true)
@DiscriminatorColumn(length = 64)
@Table(name = "rcproductservicetracer")
public class RCProductServiceTracerImpl extends BaseModelObject implements RCProductServiceTracer {
  public RCProductServiceTracerImpl() {
    super();
  }
  
  @JoinColumn(name = "budgetContract_id")
  @ManyToOne(targetEntity = RCBudgetContractImpl.class, cascade = { CascadeType.MERGE, CascadeType.PERSIST })
  private RCBudgetContract budgetContract;
  
  public RCBudgetContract getBudgetContract() {
    return this.budgetContract;
  }
  
  public RCProductServiceTracer setBudgetContract(final RCBudgetContract budgetContract) {
    this.budgetContract = budgetContract;
    return this;			
    
  }
  
  @JoinColumn(name = "companyService_id")
  @ManyToOne(targetEntity = RCCompanyServiceEntryImpl.class, cascade = { CascadeType.MERGE, CascadeType.PERSIST })
  private RCCompanyServiceEntry companyService;
  
  public RCCompanyServiceEntry getCompanyService() {
    return this.companyService;
  }
  
  public RCProductServiceTracer setCompanyService(final RCCompanyServiceEntry companyService) {
    this.companyService = companyService;
    return this;			
    
  }
  
  @JoinColumn(name = "product_id")
  @ManyToOne(targetEntity = RCIdentifiablePhysicalProductEntryImpl.class, cascade = { CascadeType.MERGE, CascadeType.PERSIST })
  private RCIdentifiablePhysicalProductEntry product;
  
  public RCIdentifiablePhysicalProductEntry getProduct() {
    return this.product;
  }
  
  public RCProductServiceTracer setProduct(final RCIdentifiablePhysicalProductEntry product) {
    this.product = product;
    return this;			
    
  }
  
  @OneToMany(targetEntity = RCActualServicePurchasedImpl.class, cascade = { CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REMOVE }, mappedBy = "tracer")
  private Collection<RCActualServicePurchased> purchased = new java.util.ArrayList<com.shrct.businessprocess.product.RCActualServicePurchased>();;
  
  public Collection<RCActualServicePurchased> getPurchased() {
    return this.purchased;
  }
  
  public RCActualServicePurchased createAndAddtoPurchased() {
    getPurchased().size();
    com.shrct.businessprocess.product.RCActualServicePurchased rCActualServicePurchased = new com.shrct.businessprocess.product.impl.RCActualServicePurchasedImpl(this);
    getObjectFactory().create(rCActualServicePurchased);
    getPurchased().add(rCActualServicePurchased);
    return rCActualServicePurchased;
    
  }
  
  public RCActualServicePurchased createAndAddtoPurchased(final Procedure1<RCActualServicePurchased> updater) {
    getPurchased().size();
    com.shrct.businessprocess.product.RCActualServicePurchased rCActualServicePurchased = new com.shrct.businessprocess.product.impl.RCActualServicePurchasedImpl(this);
    getObjectFactory().create(rCActualServicePurchased);
    getPurchased().add(rCActualServicePurchased);
    return rCActualServicePurchased;
    
  }
  
  public RCProductServiceTracer removeAllPurchased() {
    for(RCActualServicePurchased obj : this.purchased){
    	getObjectFactory().delete(obj);
    }
    this.purchased.clear();
    return this;	
    
  }
  
  public RCProductServiceTracer removeFromPurchased(final RCActualServicePurchased rCActualServicePurchased) {
    this.purchased.remove(rCActualServicePurchased);
    getObjectFactory().delete(rCActualServicePurchased);
    return this;
    
  }
  
  public RCHasPurchaseBudget getBudget() {
    RCBudget _budget = this.budgetContract.getBudget();
    return ((RCHasPurchaseBudget) _budget);
  }
  
  public Date getSupplierToDate() {
    final Function1<RCActualServicePurchased,RCFullServiceProductEntry> _function = new Function1<RCActualServicePurchased,RCFullServiceProductEntry>() {
        public RCFullServiceProductEntry apply(final RCActualServicePurchased it) {
          RCFullServiceProductEntry _fullService = it.getFullService();
          return _fullService;
        }
      };
    Iterable<RCFullServiceProductEntry> _map = IterableExtensions.<RCActualServicePurchased, RCFullServiceProductEntry>map(this.purchased, _function);
    final Function1<RCFullServiceProductEntry,Date> _function_1 = new Function1<RCFullServiceProductEntry,Date>() {
        public Date apply(final RCFullServiceProductEntry it) {
          Date _end = it.getEnd();
          return _end;
        }
      };
    List<RCFullServiceProductEntry> _sortBy = IterableExtensions.<RCFullServiceProductEntry, Date>sortBy(_map, _function_1);
    RCFullServiceProductEntry _last = IterableExtensions.<RCFullServiceProductEntry>last(_sortBy);
    Date _end = _last==null?(Date)null:_last.getEnd();
    return _end;
  }
  
  public RCProductServiceStatus getStatus() {
    boolean _equals = Objects.equal(this.companyService, null);
    if (_equals) {
      return RCProductServiceStatus.notRequired;
    }
    Date _supplierToDate = this.getSupplierToDate();
    boolean _equals_1 = Objects.equal(_supplierToDate, null);
    if (_equals_1) {
      return RCProductServiceStatus.needPurchase;
    }
    Date _end = this.companyService.getEnd();
    Date _supplierToDate_1 = this.getSupplierToDate();
    boolean _after = _end.after(_supplierToDate_1);
    if (_after) {
      Date _supplierToDate_2 = this.getSupplierToDate();
      Date _day = DateUtil.today();
      boolean _after_1 = _supplierToDate_2.after(_day);
      if (_after_1) {
        return RCProductServiceStatus.normal;
      } else {
        return RCProductServiceStatus.needPurchase;
      }
    } else {
      return RCProductServiceStatus.finished;
    }
  }
  
  public Boolean needAdditionalPurchase() {
    boolean _xblockexpression = false;
    {
      final RCProductServiceStatus s = this.getStatus();
      boolean _or = false;
      boolean _equals = Objects.equal(s, RCProductServiceStatus.needPurchase);
      if (_equals) {
        _or = true;
      } else {
        boolean _equals_1 = Objects.equal(s, RCProductServiceStatus.normal);
        _or = (_equals || _equals_1);
      }
      _xblockexpression = (_or);
    }
    return Boolean.valueOf(_xblockexpression);
  }
  
  public void serviceImported(final RCFullServiceProductEntry fullService) {
    RCActualServicePurchased _createAndAddtoPurchased = this.createAndAddtoPurchased();
    final Procedure1<RCActualServicePurchased> _function = new Procedure1<RCActualServicePurchased>() {
        public void apply(final RCActualServicePurchased it) {
          it.setFullService(fullService);
          Date _day = DateUtil.today();
          it.setImportDate(_day);
        }
      };
    ObjectExtensions.<RCActualServicePurchased>operator_doubleArrow(_createAndAddtoPurchased, _function);
  }
  
  public static RCProductServiceTracer create(final IObjectFactory objectFactory) {
    com.shrct.businessprocess.product.RCProductServiceTracer rCProductServiceTracer = new com.shrct.businessprocess.product.impl.RCProductServiceTracerImpl(
    );
    objectFactory.create(rCProductServiceTracer);
    return rCProductServiceTracer;			
    
  }
  
  public static RCProductServiceTracer createRCProductServiceTracerImpl(final IObjectFactory objectFactory, final Procedure1<RCProductServiceTracer> init) {
    com.shrct.businessprocess.product.RCProductServiceTracer rCProductServiceTracer = new com.shrct.businessprocess.product.impl.RCProductServiceTracerImpl(
    );
    objectFactory.create(rCProductServiceTracer);
    init.apply(rCProductServiceTracer);
    
    return rCProductServiceTracer;			
    
  }
  
  public RCProductServiceTracerProxy toProxy() {
    com.shrct.businessprocess.product.proxy.RCProductServiceTracerProxy proxy = new com.shrct.businessprocess.product.proxy.RCProductServiceTracerProxy();
    proxy.setId(this.getId());
    if(this instanceof edu.fudan.mylang.pf.INamedModelObject){
    	proxy.setName(((edu.fudan.mylang.pf.INamedModelObject)this).getEntityName());
    }
    return proxy;
    
  }
}
